package cn.jsu.oj.dispatchServer.net;

import cn.jsu.oj.dispatchServer.init.ClientInitVector;
import cn.jsu.oj.dispatchServer.pojo.AbstractPack;
import cn.jsu.oj.dispatchServer.utils.NetUtil;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import lombok.extern.slf4j.Slf4j;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author ahtonc
 */
@Slf4j
@ChannelHandler.Sharable
public class DispatchServerHandle extends ChannelInboundHandlerAdapter {

    public static Map<String, ClientInitVector> vectorMap = new ConcurrentHashMap<>();

    public static Map<String, String> realIdentityMap = new ConcurrentHashMap<>();

    /**
     * 有新连接时创建客户端容器
     *
     * @param ctx 通道
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        log.info(ctx.channel().remoteAddress() + "----------任务机已连接......");
        createVector(ctx.channel());
        super.channelActive(ctx);
    }

    /**
     * 读到一个信息，并添加到对应客户端容器
     *
     * @param ctx 通道
     * @param msg 实体类
     * @description 从通道中拿到包 塞到对应的消息队列中
     * 然后交由对应的Client#run 方法找到对应的处理类处理
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        log.info("----------数据收到......" + msg);
        AbstractPack abstractPack = (AbstractPack) msg;
        //将数据包类型区分出来
        short typeNo = abstractPack.getTypeNo();
        log.warn("typeNO--------------"+typeNo);
        if (typeNo == 93 || typeNo == 94 || typeNo == 95) {
            vectorMap.get(NetUtil.getIdentify(ctx.channel())).addTask(msg);
        } else {

            vectorMap.get(realIdentityMap.get(NetUtil.getIdentify(ctx.channel()))).addTask(msg);
        }
        super.channelRead(ctx, msg);
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        String ipAndPort = NetUtil.getIdentify(ctx.channel());
        log.info("通道关闭移除Map" + NetUtil.getIdentify(ctx.channel()));
        //关闭容器
        String realIpAndPort = realIdentityMap.get(ipAndPort);
        realIdentityMap.remove(ipAndPort);
        vectorMap.get(realIpAndPort).close();
        //移除映射
        vectorMap.remove(realIpAndPort);
        super.channelInactive(ctx);
    }


    /**
     * 创建客户端容器
     *
     * @param channel 通道
     */
    private void createVector(Channel channel) {
        ClientInitVector clientInitVector = new ClientInitVector();
        clientInitVector.init(channel);
        String ipAndPort = NetUtil.getIdentify(channel);
        System.out.println(ipAndPort);
        vectorMap.put(ipAndPort, clientInitVector);
        new Thread(() -> clientInitVector.run(), "ClientThread").start();
    }
}
